package com.bookmanager.www.common.config;

import com.bookmanager.www.common.fitter.JwtFilter;
import com.bookmanager.www.common.realm.UserRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 *
 * @author: 风离
 * @Date: 2021/09/19/9:41
 * @Description:
 */

import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SubjectFactory;

import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.filter.authc.LogoutFilter;


import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * springBoot整合jwt实现认证有三个不一样的地方，对应下面abc
 */
@Configuration
public class ShiroConfig {
    /**
     * a. 告诉shiro不要使用默认的DefaultSubject创建对象，因为不能创建Session
     * */
    @Bean
    public SubjectFactory subjectFactory() {
        return new JwtDeafultSubjectFactory();
    }
    @Bean
    public Realm realm() {
        return new UserRealm();
    }



    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm());
        //++++++++++++++++++++++++++++++++ new +++++++++++++++++++++++++++++++++++++++++++++++
        //设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);
        //获取认证主体
        Subject subject = SecurityUtils.getSubject();
        System.err.println("用户认证状态1====>"+subject.isAuthenticated());


        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


        /*
         * b
         * */
        // 关闭 ShiroDAO 功能
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        // 不需要将 Shiro Session 中的东西存到任何地方（包括 Http Session 中）
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        //禁止Subject的getSession方法
        securityManager.setSubjectFactory(subjectFactory());
        return securityManager;
    }


    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager());
        //前端需要创建这两个页面 一个是未认证页面 一个是未授权页面
        shiroFilter.setLoginUrl("/unauthenticated");
        shiroFilter.setUnauthorizedUrl("/unauthorized");
        /**
         * c. 添加jwt过滤器，并在下面注册
         * 也就是将jwtFilter注册到shiro的Filter中
         * 指定除了login和logout之外的请求都先经过jwtFilter
         * */
        Map<String, Filter> filterMap = new HashMap<>();
        //这个地方其实另外两个filter可以不设置，默认就是
        filterMap.put("anon", new AnonymousFilter());
        filterMap.put("jwt", new JwtFilter());
        filterMap.put("logout", new LogoutFilter());
        shiroFilter.setFilters(filterMap);

        // 拦截器
        Map<String, String> filterRuleMap = new LinkedHashMap<>();

        /**
         * 放行Swagger
         */
        //放行Swagger2页面，需要放行这些
        filterRuleMap.put("/swagger-ui/index.html","anon");
        filterRuleMap.put("/swagger/**","anon");
        filterRuleMap.put("/webjars/**", "anon");
        filterRuleMap.put("/swagger-resources/**","anon");
        filterRuleMap.put("/v2/**","anon");
        filterRuleMap.put("/static/**", "anon");
        filterRuleMap.put("/doc.html", "anon");

         //测试
        filterRuleMap.put("/addOrder", "anon");


        /**
         * 用户登录 用户注册 判断用户是否存在 获取图书列表 获取分类图书列表放行
         */
        filterRuleMap.put("/fl-registerOrLogin/**", "anon");

        //判断用户存在放行
        filterRuleMap.put("/fl-searchUser/**", "anon");
        //验证码操作放行
        filterRuleMap.put("/code/**", "anon");
        
        //放行查询图书
        filterRuleMap.put("/fl-searchBook/**","anon");

        //放行支付接口
        filterRuleMap.put("/aliPay/**","anon");
        filterRuleMap.put("/wxPay/**","anon");

        //放行第三方登录接口
        filterRuleMap.put("/oauth2/**","anon");

//        filterRuleMap.put("/fl-book/getAllBooks", "anon");
        filterRuleMap.put("/fl-book/shufflingFigure", "anon");
        filterRuleMap.put("/fl-book/getCategoriesBooks", "anon");
        filterRuleMap.put("/fl-book/zeroBuyBook", "anon");

        filterRuleMap.put("/fl-categories/byCategory", "anon");
//        filterRuleMap.put("", "anon");
//        filterRuleMap.put("", "anon");
//        filterRuleMap.put("", "anon");
//        filterRuleMap.put("", "anon");


        filterRuleMap.put("/fl-categories/getAllCategories", "anon");
        filterRuleMap.put("/fl-categories/getAllClassify", "anon");

        // 放行通用插件
        filterRuleMap.put("/fl-common/**","anon");

//        filterRuleMap.put("/**", "anon");

        /**
         * 所有请求都要通过JWT 如果没有Token则无法访问
         */
        filterRuleMap.put("/**", "jwt");
        shiroFilter.setFilterChainDefinitionMap(filterRuleMap);

        return shiroFilter;
    }


    /**
     * 以下Bean开启shiro权限注解
     *
     * @return DefaultAdvisorAutoProxyCreator
     */
    @Bean
    public static DefaultAdvisorAutoProxyCreator creator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
}

